package com.ym.wcp.framework.aop;

import com.ym.wcp.framework.annotation.LoginPwdErrorLock;
import com.ym.wcp.framework.exception.LoginPwdErrorException;
import com.ym.wcp.framework.response.R;
import com.ym.wcp.framework.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
@Slf4j
public class LoginPwdErrorLockAop {

    @Autowired
    private RedisUtil redis;

    @Around("execution(public * *(..)) && @annotation(com.ym.wcp.framework.annotation.LoginPwdErrorLock)")
    public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        LoginPwdErrorLock ann = method.getAnnotation(LoginPwdErrorLock.class);
        int errorCount = ann.errorCount();
        int unLockMinute = ann.unLockMinute();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String sessionId = request.getSession().getId();
        if (StringUtils.isEmpty(sessionId)) {
            throw new Throwable("未开启session，LoginPwdErrorLock无法生效");
        }
        String loginLockKey = "loginLock-" + request.getSession().getId();
        String loginCountKey = "loginCount-" + request.getSession().getId();
        try {
            Object proceed = pjp.proceed();
            redis.del(loginCountKey);
            redis.del(loginLockKey);
            return proceed;
        } catch (Throwable e) {
            if (e instanceof LoginPwdErrorException) {
                Object isLock = redis.get(loginLockKey);
                if (isLock == null) {
                    long count = redis.increment(loginCountKey, 1);
                    if (count >= errorCount) {
                        redis.put(loginLockKey, request.getSession().getId(), unLockMinute, TimeUnit.MINUTES);
                        redis.del(loginCountKey);
                        return R.result(-1, null, "账号已锁定请" + unLockMinute + "分钟后重试");
                    }
                    return R.result(-1, null, "账号或密码错误" + (errorCount - count) + "次");
                }
                return R.result(-1, null, "账号已锁定请" + unLockMinute + "分钟后重试");
            }
            throw e;
        }
    }
}
